package com.atguigu.gmall.cart.interceptor;

import com.atguigu.gmall.cart.bean.UserInfo;
import com.atguigu.gmall.cart.config.AuthJwtProperties;
import com.atguigu.gmall.common.utils.CookieUtils;
import com.atguigu.gmall.common.utils.JwtUtils;
import com.atguigu.gmall.common.utils.RsaUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.UUID;

@Component
public class UserInfoInterceptor implements HandlerInterceptor {
    private static final ThreadLocal<UserInfo> LOCAL = new ThreadLocal<>();

//    public UserInfoInterceptor(AuthJwtProperties jwtProperties) {
//        this.jwtProperties = jwtProperties;
//    }

    // 只能在组件类中 使用：从容器中获取对象装配
    @Autowired
    AuthJwtProperties jwtProperties;
    @Autowired
    RedisTemplate redisTemplate;
    //对请求预处理
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //生成一个UserKey或者userId 交给后续的业务使用
        // 无论用户是否登录：都给他设置userKey
        //1、如果请求报文中存在userKey直接将userKey获取存到ThreadLocal中
        String userKey = CookieUtils.getCookieValue(request, jwtProperties.getCookieName());
        if(StringUtils.isEmpty(userKey)){
            //2、如果不存在userKey 生成一个userKey 存到ThreadLocal中
            // 如果userKey是本次创建的  设置为cookie
            userKey = UUID.randomUUID().toString().replace("-","");
            CookieUtils.setCookie(request,response,jwtProperties.getCookieName() ,userKey,
                    60*60*24*30);
            //设置UserKey的购物车的过期时间和userKey的cookie一样
//            String cartKey = "cart:"+userKey;
//            BoundHashOperations ops = redisTemplate.boundHashOps(cartKey);
        }
        UserInfo userInfo = new UserInfo();
        userInfo.setUserKey(userKey);

        //3、获取请求报文头中的userId，如果获取成功 可以将userId也存到ThreadLocal中
        String userId = request.getHeader(jwtProperties.getHeaderName());
        if(StringUtils.isEmpty(userId)){
           //只有给当前的服务在网关中的路由配置了 Auth过滤器，它才会取出请求报文cookie中的GMALL-TOKEN
            //中的userId设置到请求头中
            //如果请求头没有UserId，从cookie中的GMALL-TOKEN中获取
            String token = CookieUtils.getCookieValue(request, jwtProperties.getTokenName());
            try {
                Map<String, Object> map = JwtUtils.getInfoFromToken(token,
                        RsaUtils.getPublicKey(jwtProperties.getPublicKeyPath()));
                userId = map.get("userId").toString();
            } catch (Exception e) {
//                e.printStackTrace();
            }
        }
        if(!StringUtils.isEmpty(userId)){
            userInfo.setUserId(userId);
        }
//        request.setAttribute("userKey" , "9527");
        /*
            使用ThreadLocal共享数据：
                能够在一次线程经过的业务方法中获取到threadLocal中共享的数据
         */
        LOCAL.set(userInfo);
        return true;//放行请求
    }
    //收尾操作
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//        System.out.println("UserInfoInterceptor  .. afterCompletion 执行了");
        //当前线程已经执行结束，它缓存再threadLocal中的数据可以移除 避免内存溢出
        // 如果触发了GC，threadLocal中的数据会被移除掉
        LOCAL.remove();
    }
    //获取userId的值
    public static String getUserId(){
        UserInfo userInfo = LOCAL.get();
        if(!StringUtils.isEmpty(userInfo.getUserId())){
            return userInfo.getUserId();
        }
        return userInfo.getUserKey();
    }
    public static UserInfo getUserInfo(){
        UserInfo userInfo = LOCAL.get();
        return userInfo;
    }
}
